# -*- coding: utf_8 -*-
# @Create   : 2021/8/20 9:23
# @Author   : yh
# @Remark   : 配置管理server层
from mxsoftpy import Server
from db.common.VideoManage.VideoQuality.conf import *
from model.common.VideoManage.VideoQuality.conf import *
from utils.public.data_process import list_dict, is_number
from mxsoftpy.exception import DataError


class ConfServer(Server):
    """基础server"""
    def __init__(self, model_s, db_s, c_fk):
        """
        :param model_s: 每个对应的Model类  --> object
        :param db_s: 每个对应的DB类  --> object
        :param c_fk: 对象数据库中的配置名 --> str
        self.update_field: update可修改字段
        self.query_field: 可查询的字段
        """
        self.db_s = db_s(c_fk)
        self.model_s = model_s
        self.update_field = ['name', 'state']
        self.query_field = ['name', 'state']
        super().__init__()


class ConfList(ConfServer):
    def list(self):
        """获取配置数据"""
        get_data_dict = self.db_s.use_keys(self.query_field)
        """list_dict 形成 data:[{},{}] 格式数据"""
        res_dict = list_dict(get_data_dict)
        res_dict['total'] = len(res_dict['data'])
        return res_dict


class ConfAdd(ConfServer):

    def add(self, **kwargs):
        """
        增加一条数据
        create_data_dict 为Model校验后的数据
        """
        create_data_dict = self.model_s(**kwargs).dict()
        """对 state字段 进行校验"""
        if create_data_dict['state'] not in [0, 1]:
            create_data_dict['state'] = 1
        return self.db_s.add(**create_data_dict)


class ConfDelete(ConfServer):

    def delete(self, code: int):
        """
        删除一条数据
        :param code: 删除数据的code
        """
        return self.db_s.delete(code)


class ConfUpdate(ConfServer):

    def update(self, **kwargs):
        """
        更新一条数据
        data_filter: 为过滤后的数据字典组
        valid_fields: 为kwargs与self.update_key的交集，即取self.update_key中的字段
        """
        data_filter = {}
        valid_fields = set(kwargs.keys()) & set(self.update_field)
        """
        过滤数据
        """
        for i in valid_fields:
            if not kwargs[i]:
                """过滤掉无内容字段"""
                continue

            if i == 'state':
                """判断状态是否规范"""
                if kwargs[i] in ['0', '1']:
                    data_filter[i] = int(kwargs[i])
                    continue
                else:
                    raise DataError('您写的状态不对，应为0或1')

            if self.check_filter(data_filter, kwargs, i):
                """自定义校验"""
                continue

            """无需校验字段"""
            data_filter[i] = kwargs[i]
        """最大值与最小值之间的比较"""
        if data_filter.get('max') and data_filter.get('min') and data_filter['max'] < data_filter['min']:
            raise DataError('您写的最小置信度大于最大置信度')

        """整理成数据库识别的格式"""
        update_list = [(key, val) for key, val in data_filter.items()]
        return self.db_s.update(kwargs['code'], update_list)

    def check_filter(self, data_filter, kwargs, i):
        """
        给子类写的校验接口， 如果子类有自定义校验，在子类写此方法，非强制
        :param data_filter: 过滤后储存的数据 --> dict
        :param kwargs: 校验的参数组 --> dict
        :param i: 具体的参数名 --> str
        """
        return False


class ConfShareServer(ConfList, ConfAdd, ConfUpdate, ConfDelete):
    """公共整合类，继承不同从请求处理方法"""
    pass


class VideoDeviceServer(ConfShareServer):
    """
    视频模型Server
    """
    def __init__(self, c_fk):
        """
        :param c_fk: 为view传过来的数据库健名 --> str
        self.model_s: 视频模型的Model类 -->object
        self.db_s: 视频模型的DB类 -->object
        super() 给ConfServer类传值，分配不同的请求给不同的类(如获取所有数据->ConfList)
        """
        self.model_s = DeviceTypeModel
        self.db_s = VideoDeviceDB
        super().__init__(model_s=self.model_s, db_s=self.db_s, c_fk=c_fk)


class StreamServer(ConfShareServer):
    """
    码流Server
    """
    def __init__(self, c_fk):
        """
        :param c_fk: 为view传过来的数据库健名 --> str
        self.model_s: 视频模型的Model类 -->object
        self.db_s: 视频模型的DB类 -->object
        super() 给ConfServer类传值，分配不同的请求给不同的类(如获取所有数据->ConfList)
        """
        self.model_s = StreamModel
        self.db_s = StreamDB
        super().__init__(model_s=self.model_s, db_s=self.db_s, c_fk=c_fk)


class ResolutionServer(ConfShareServer):
    """
    分辨率Server
    """
    def __init__(self, c_fk):
        """
        :param c_fk: 为view传过来的数据库健名 --> str
        self.model_s: 视频模型的Model类 -->object
        self.db_s: 视频模型的DB类 -->object
        super() 给ConfServer类传值，分配不同的请求给不同的类(如获取所有数据->ConfList)
        """
        self.model_s = ResolutionModel
        self.db_s = ResolutionDB
        super().__init__(model_s=self.model_s, db_s=self.db_s, c_fk=c_fk)


class TaskCycleServer(ConfShareServer):
    """
    任务周期Server
    """
    def __init__(self, c_fk):
        """
        :param c_fk: 为view传过来的数据库健名 --> str
        self.model_s: 视频模型的Model类 -->object
        self.db_s: 视频模型的DB类 -->object
        super() 给ConfServer类传值，分配不同的请求给不同的类(如获取所有数据->ConfList)
        self.update_field: update可修改字段
        self.query_field: 可查询的字段
        """
        self.model_s = TaskCycleModel
        self.db_s = TaskCycleDB
        super().__init__(model_s=self.model_s, db_s=self.db_s, c_fk=c_fk)
        self.update_field = ['name', 'state', 'minute']
        self.query_field = ['name', 'state', 'minute']

    def check_filter(self, data_filter, kwargs, i):
        """
        子类自定义校验
        :param data_filter: 过滤后储存的数据 --> dict
        :param kwargs: 校验的参数组 --> dict
        :param i: 具体的参数名 --> str
        """
        if i == 'minute':
            """判断时间是否规范"""
            if kwargs[i].isdigit():
                data_filter[i] = int(kwargs[i])
                return True
            else:
                raise DataError('您写的时间类型不对，单位是：分钟')
        return False


class TestItemsServer(ConfShareServer):
    """
    检测项目类型Server
    """
    def __init__(self, c_fk):
        """
        :param c_fk: 为view传过来的数据库健名 --> str
        self.model_s: 视频模型的Model类 -->object
        self.db_s: 视频模型的DB类 -->object
        super() 给ConfServer类传值，分配不同的请求给不同的类(如获取所有数据->ConfList)
        self.update_field: update可修改字段
        self.query_field: 可查询的字段
        """
        self.model_s = TestItemsModel
        self.db_s = TestItemsDB
        super().__init__(model_s=self.model_s, db_s=self.db_s, c_fk=c_fk)
        self.update_field = ['name', 'state', 'max', 'min', 'expression', 'reference','func_name','func_args']
        self.query_field = ['name', 'state', 'max', 'min', 'expression', 'reference','func_name','func_args', 'step']

    def add(self, **kwargs):
        """
        增加一条数据
        valid_fields 为Model校验的数据
        """
        valid_fields = self.model_s(**kwargs).dict()
        """
        对数据进行校验
        """

        if valid_fields['state'] not in [0, 1]:
            valid_fields['state'] = 1
        if valid_fields['min'] < 0:
            raise DataError('您添加的最小置信度的可信度小于1，最低为1')
        if valid_fields['min'] > 100:
            raise DataError('您添加的最小置信度的可信度大于100，最大为99')
        if valid_fields['max'] > 100:
            raise DataError('您添加的最大置信度的可信度大于100，最大为100')
        if valid_fields['max'] <= valid_fields['min']:
            raise DataError('您添加的最大置信度小于最小置信度')

        """
        为DB新增数据的方法
        """
        return self.db_s.add(**valid_fields)

    def check_filter(self, data_filter, kwargs, i):
        """
        子类自定义校验
        :param data_filter: 过滤后储存的数据 --> dict
        :param kwargs: 校验的参数组 --> dict
        :param i: 具体的参数名 --> str
        """
        if i == 'max':
            """判断max(最大值)是否规范"""
            if is_number(kwargs[i]) and 2 <= float(kwargs[i]) <= 100:
                data_filter[i] = float(kwargs[i])
                return True

            else:
                raise DataError('您写的最大置信度数据类型不对或值不在 2-100 之间')
        if i == 'min':
            """判断min(最小值)是否规范"""
            if is_number(kwargs[i]) and 1 <= float(kwargs[i]) <= 99:
                data_filter[i] = float(kwargs[i])
                return True
            else:
                raise DataError('您写的最小置信度数据类型不对或值不在 1-99 之间')

        if i == 'reference':
            if is_number(kwargs[i]) and 0 < float(kwargs[i]) < 100:
                data_filter[i] = float(kwargs[i])
                return True
            else:
                raise DataError('您写的参考值数据类型不对或超出最大范围')
        return False

